package com.net.core.models;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.net.core.core.YXException;
import com.net.core.core.reuslt.MyPage;
import com.net.core.core.reuslt.PageResp;
import com.net.core.core.sql.BatchSql;
import com.net.core.core.sql.YxSql;
import com.net.core.core.sql.YxSqlPlus;
import com.net.core.core.sql.PageUtils;
import com.net.core.utils.MyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Slf4j
public class BaseDao {

    @Resource
    protected JdbcTemplate jdbcTemplate;

    protected <T> List<T> selectList(YxSql sql, Class<T> clz) {
        List<Map<String, Object>> list = executeSql(sql.toSql(), sql.getValues(), sql.isLog());
        List<T> ts = mapToObj(list, clz);
        return ts;
    }

    protected  List<Map<String, Object>> selectList(YxSql sql) {
        List<Map<String, Object>> list = executeSql(sql.toSql(), sql.getValues(), sql.isLog());
        return list;
    }

    protected <T> T select(YxSqlPlus<T> sql, Class<T> clz) {
        List<T> ts = selectList(sql, clz);
        if (ts != null && ts.size() > 1) {
            throw new YXException("查询出多个结果");
        }
        if (ts != null && ts.size() > 0) {
            //TODO  这里继续调用selectlist方法 会在执行一次sql.toSql()方法 导致出现sql语句问题
//            return selectList(sql,clz).get(0);
            return ts.get(0);
        }
        return null;
    }

    protected List<Map<String, Object>> getTableNotes(String tableName) {


        String sql = "select t.column_name as [key],t.column_description as [name] from (\n" +
                "SELECT A.name AS table_name,B.name AS column_name, C.value AS column_description \n" +
                "FROM objmanager.sys.tables A\n" +
                "INNER JOIN objmanager.sys.columns B ON B.object_id = A.object_id\n" +
                "LEFT JOIN objmanager.sys.extended_properties C ON C.major_id = B.object_id AND C.minor_id = B.column_id\n" +
                "WHERE A.name = ?) t";
        List<Map<String, Object>> list = executeSql(sql, new Object[]{tableName}, true);
        return list;
    }

    @Transactional
    public int delete(YxSqlPlus sql, int effect) {
        return update(sql, effect);
    }

    @Transactional
    public int update(YxSql sql, int effect) {
        int update = 0;
        update = updateSql(sql.toSql(), sql.getValues(), sql.isLog());
        if (update > effect) {
            throw new YXException("本次更新：" + update + "条数据 超过了你的预估值：" + effect + "条");
        }
        return update;
    }

    @Transactional
    public int update(YxSql sql) {
        int update = updateSql(sql.toSql(), sql.getValues(), sql.isLog());
        return update;
    }

    private int updateSql(String sql, Object[] values, boolean isLog) {
        if (isLog) printLog(sql, values);
        int update = jdbcTemplate.update(sql, values);
        return update;
    }

    protected int insert(YxSqlPlus sql) {
        int update = updateSql(sql.toSql(), sql.getValues(), sql.isLog());
        return update;
    }

    protected Long insertReturnId(YxSqlPlus sql) {
        int update = updateSql(sql.toSql(), sql.getValues(), sql.isLog());
        Long lastId = getLastId(sql);
        return lastId;
    }

    public static <T> T mapToObj(Map<String, Object> results, Class<T> clz) {
        JSONObject jsonObject = new JSONObject(results);
        T t = jsonObject.toJavaObject(clz);
        return t;
    }

    public static <T> List<T> mapToObj(List<Map<String, Object>> results, Class<T> clz) {
        JSONArray array = new JSONArray();
        array.addAll(results);
        List<T> list = array.toJavaList(clz);
        return list;
    }

    private List<Map<String, Object>> executeSql(String sql, Object[] values, boolean isLog) {
        if (isLog) printLog(sql, values);
        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, values);
        return list;
    }

    private void printLog(String sql, Object[] values) {
        StringBuilder sqlStr = new StringBuilder(sql);
        for (int i = 0; i < values.length; i++) {
            int i1 = sqlStr.indexOf("?");
            Object o = values[i];
            if (values[i] instanceof Date) {
                o = new Timestamp(((Date) o).getTime());
            }
            sqlStr.replace(i1, i1 + 1, values[i] == null ? "" : "'" + o.toString() + "'");
        }
        log.debug(sqlStr.toString());
    }

    public <T> int batchInsert(List<T> objects) {
        YxSqlPlus yxYearSql = new YxSqlPlus(objects.get(0).getClass());
        BatchSql sql = new BatchSql(yxYearSql, objects);
        sql.insertBatch();
        List<Object[]> batchData = sql.getBatchData();
        int[] ints = this.batchUpdateSql(sql.toSql(), batchData, objects.size());
        return this.getInts(ints);
    }

    @Transactional
    public int[] batchUpdateSql(String sql, List<Object[]> batchData, int effect) {
        this.printLog(sql, batchData);
        int[] update = this.jdbcTemplate.batchUpdate(sql, batchData);
        int ints = this.getInts(update);
        if (ints > effect) {
            throw new YXException("本次更新：" + update + "条数据 超过了你的预估值：" + effect + "条");
        } else {
            return update;
        }
    }

    private int getInts(int[] ints) {
        if (ints == null) {
            return 0;
        } else {
            int total = 0;
            int[] var3 = ints;
            int var4 = ints.length;

            for (int var5 = 0; var5 < var4; ++var5) {
                int i = var3[var5];
                total += i;
            }

            return total;
        }
    }

    private void printLog(String sql, List<Object[]> values) {
        for (int i = 0; i < values.size(); ++i) {
            this.printLog(sql, (Object[]) values.get(i));
        }
    }

    protected <T> PageResp<T> selectListPage(YxSqlPlus sql, MyPage page, Class<T> clz) {
        PageResp<T> pageResp = new PageResp();
        PageUtils yxSqlPage = new PageUtils(sql, page);
        Map<String, Object> map = this.jdbcTemplate.queryForMap(yxSqlPage.getCountSql(), sql.getValues());
        List<Map<String, Object>> list = this.executeSql(yxSqlPage.toSql(), sql.getValues(), sql.isLog());
        List<T> ts = MyUtils.MapToObj(list, clz);
        pageResp.setCurrent(page.getCurrent());
        pageResp.setSize(page.getSize());
        pageResp.setTotal((long) (Integer) map.get("total"));
        pageResp.setRecords(ts);
        return pageResp;
    }

    protected int getCount(YxSqlPlus sql) {
        int count = 0;
        List<Map<String, Object>> list = executeSql(sql.getCountSql(), sql.getValues(), sql.isLog());
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = list.get(i);
            Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
            if (iterator.hasNext()) {
                Map.Entry<String, Object> next = iterator.next();
                Object value = next.getValue();
                Integer total = Integer.parseInt(value.toString());
                count += total;
            }
        }
        return count;
    }

    public Long getLastId(YxSqlPlus yxSqlPlus) {
        List<Map<String, Object>> list = jdbcTemplate.queryForList("select top 1 id from "+yxSqlPlus.getTableName()+" order by id DESC");
        if(list.size()==0){
            return 0L;
        }else {
            Object id = list.get(0).get("id");
            return Long.parseLong(id.toString());
        }
    }

}
